package com.jiandian.service.impl;


import com.jiandian.constant.SignLogConstants;
import com.jiandian.dao.SignLogMapper;
import com.jiandian.entity.SignLog;
import com.jiandian.entity.SignUser;
import com.jiandian.exception.SuppleException;
import com.jiandian.page.PageInfo;
import com.jiandian.page.WhereMapUtil;
import com.jiandian.service.SignLogService;
import com.jiandian.service.SignPrizeLogService;
import com.jiandian.util.BeanUtils;
import com.jiandian.util.DateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

/**
 * 签到记录
 *
 * @author houqi Fu
 * @date 2018/12/15
 */
@Service
@Transactional
public class SignLogServiceImpl implements SignLogService {

    private static final Logger logger = LoggerFactory.getLogger(SignLogServiceImpl.class);

    @Autowired
    private SignLogMapper mapper;

    @Autowired
    private SignPrizeLogService signPrizeLogService;


    @Override
    public SignLog add(SignLog record) {

        initBasicValue(record);

        int result = mapper.insert(record);
        if (result > 0) {
            return record;
        }
        return null;
    }

    @Override
    public SignLog update(SignLog record) {
        Long id = record.getId();
        if (id == null) {
            return null;
        }
        SignLog dbSignLog = mapper.selectByPrimaryKey(id);
        if (dbSignLog == null) {
            return null;
        }
        BeanUtils.copyProperties(record, dbSignLog);
        // dbSignLog.setGmtModified(new Timestamp(System.currentTimeMillis()));
        int result = mapper.updateByPrimaryKey(dbSignLog);
        if (result > 0) {
            return dbSignLog;
        }
        return null;
    }

    @Override
    public SignLog findById(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public List<SignLog> findAll(PageInfo pageInfo) {
        return mapper.selectAll(pageInfo);
    }

    @Override
    public int selectCount(PageInfo pageInfo) {
        return mapper.selectCount(pageInfo);
    }

    @Override
    public int batchInsert(List<SignLog> list) {
        for (SignLog bean : list) {
            initBasicValue(bean);
        }
        return mapper.batchInsert(list);
    }

    @Override
    public List<SignLog> batchQueryByIds(List<Long> ids) {
        return mapper.batchQueryByIds(ids);
    }

    @Override
    public int delete(Long id) {
        return mapper.deleteByPrimaryKey(id);
    }

    @Override
    public int delete(SignLog record) {
        return delete(record.getId());
    }

    @Override
    public int batchDeleteById(List<Long> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            return mapper.batchDeleteById(ids);
        }
        return 0;
    }

    @Override
    public PageInfo getPage(SignLog whereEntity, PageInfo pageInfo) {
        pageInfo.setWhereMap(WhereMapUtil.convertBeanToWhereMap(whereEntity));
        pageInfo.setTotalRecord(selectCount(pageInfo));
        pageInfo.queryPageResult(pageInfo);
        pageInfo.setResultObject(findAll(pageInfo));
        return pageInfo;
    }


    @Override
    public int clacContinueSignDays(int userId) {
        LinkedList<LocalDate> localDates = new LinkedList<>();
        List<SignLog> signLogs = mapper.selectByUserId(userId);

        SignLog lastSignLog = signLogs.get(0);
        LocalDate lastSignLogDate = lastSignLog.getCreateTime().toLocalDateTime().toLocalDate();

        // 判断最后一次签到日期到目前的天数差，如果大于1说明最后一次是断签的,连续签到天数为0
        long interval = DateUtil.calcIntervalDays(lastSignLogDate, LocalDate.now());
        if (interval > 1) {
            return 0;
        }

        int count = 1;
        for (SignLog signLog : signLogs) {
            Timestamp createTime = signLog.getCreateTime();
            LocalDate localDate = createTime.toLocalDateTime().toLocalDate();
            localDates.add(localDate);
            if (localDates.size() == 2) {
                LocalDate pop = localDates.pop();
                long intervalDays = DateUtil.calcIntervalDays(localDate, pop);
                // 如果不是连续的两天
                if (intervalDays != 1L) {
                    break;
                }
                count++;
            }
        }
        return count;
    }

    @Override
    public void addSuppleSignLog(int userId, LocalDate time) {
        SignLog signLog = new SignLog();
        LocalDateTime of = LocalDateTime.of(time.minusDays(1L), LocalTime.NOON);
        signLog.setCreateTime(Timestamp.valueOf(of));
        signLog.setUserId(userId);
        signLog.setSignMachine(SignLogConstants.SUPPLEMENT_MACHINE_NUMBE);
        mapper.insert(signLog);
    }

    @Override
    public List<SignLog> selectByUserId(int userId) {
        return mapper.selectByUserId(userId);
    }

    @Override
    public SignUser consumeSupplement(SignUser signUser, int intervalDayCount, int supplementCount, LocalDate lastDate) {
        if(intervalDayCount<=0||supplementCount<=0){
            logger.error("Id为{}的用户数据有误",signUser.getId());
            throw new SuppleException("补签失败，请联系管理员");
        }
        // 补签卡数量与断签天数做比较，补签天数取小的
        int useSupplement = Math.toIntExact(intervalDayCount < supplementCount ? intervalDayCount : supplementCount);
        for (int i = 0; i < useSupplement; i++) {
            LocalDate preSuppleDay = lastDate.minusDays(i);
            // lastDate.plusDays(i);
            addSuppleSignLog(signUser.getId(), preSuppleDay);
            // 使用最先获得的补签卡
            signPrizeLogService.consumeSupplement(signUser.getId(), 1);
        }

        signUser.setUsedSupplementCount(signUser.getUsedSupplementCount() + useSupplement);
        signUser.setSupplementCount(signUser.getSupplementCount() - useSupplement);
        return signUser;
    }

    @Override
    public SignLog getLastSignDay(int userId) {
        return mapper.getLastSignDay(userId);
    }

    private void initBasicValue(SignLog record) {
        Timestamp now = new Timestamp(System.currentTimeMillis());
        record.setCreateTime(now);
    }

}
